home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers3.zip / NE2100.ASM < prev    next >
Assembly Source File  |  1992-03-14  |  19KB  |  816 lines

  1. version    equ    1
  2.  
  3. ; Copyright, 1990, Russell Nelson
  4.  
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation, version 1.
  8. ;
  9. ;   This program is distributed in the hope that it will be useful,
  10. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;   GNU General Public License for more details.
  13. ;
  14. ;   You should have received a copy of the GNU General Public License
  15. ;   along with this program; if not, write to the Free Software
  16. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.     .286                ;the NE2100 requires a 286.
  20.  
  21.     include    defs.asm
  22.  
  23. DATA_REG    equ    10h
  24. ADDR_REG    equ    DATA_REG+2
  25. NODE_REG    equ    DATA_REG-10h
  26.     CSR0        equ    0
  27.     CSR1        equ    1
  28.     CSR2        equ    2
  29.     CSR3        equ    3
  30.  
  31. DMA_8MASK_REG    equ    0Ah
  32. DMA_16MASK_REG    equ    0D4h
  33.  
  34. DMA_8MODE_REG    equ    0Bh
  35. DMA_16MODE_REG    equ    0D6h
  36.  
  37. CASCADE_MODE      equ    0C0h
  38. SET_DMA_MASK      equ    4
  39. DMA_CHANNEL_FIELD equ    3
  40.  
  41.  
  42. outport    macro    reg
  43.     push    ax
  44.     mov    dx,io_addr
  45.     add    dx,ADDR_REG
  46.     mov    ax,reg
  47.     out    dx,ax
  48.     in    ax,dx            ;always follow a write by a read
  49.  
  50.     dec    dx            ;DATA_REG
  51.     dec    dx
  52.     pop    ax
  53.     out    dx,ax
  54.     in    ax,dx            ;always follow a write by a read
  55.  
  56.     endm
  57.  
  58.  
  59. ;
  60. ;     Control and Status Register 0 (CSR0) bit definitions
  61. ;
  62. CSR0_ERR    equ     8000h    ; Error summary
  63. CSR0_BABL    equ     4000h    ; Babble transmitter timeout error
  64. CSR0_CERR    equ    2000h    ; Collision Error
  65. CSR0_MISS    equ    1000h    ; Missed packet
  66. CSR0_MERR    equ    0800h    ; Memory Error
  67. CSR0_RINT    equ    0400h    ; Reciever Interrupt
  68. CSR0_TINT       equ    0200h    ; Transmit Interrupt
  69. CSR0_IDON    equ    0100h    ; Initialization Done
  70. CSR0_INTR    equ    0080h    ; Interrupt Flag
  71. CSR0_INEA    equ    0040h    ; Interrupt Enable
  72. CSR0_RXON    equ    0020h    ; Receiver on
  73. CSR0_TXON    equ    0010h   ; Transmitter on
  74. CSR0_TDMD    equ    0008h    ; Transmit Demand
  75. CSR0_STOP    equ    0004h     ; Stop
  76. CSR0_STRT    equ    0002h    ; Start
  77. CSR0_INIT    equ    0001h    ; Initialize
  78.  
  79. ;
  80. ;     Initialization Block  Mode operation Bit Definitions.
  81. ;
  82. M_PROM        equ    8000h    ; Promiscuous Mode
  83. M_INTL        equ    0040h   ; Internal Loopback
  84. M_DRTY        equ    0020h   ; Disable Retry
  85. M_COLL        equ    0010h    ; Force Collision
  86. M_DTCR        equ    0008h    ; Disable Transmit CRC)
  87. M_LOOP        equ    0004h    ; Loopback
  88. M_DTX        equ    0002h    ; Disable the Transmitter
  89. M_DRX        equ    0001h   ; Disable the Reciever
  90.  
  91.  
  92. ;
  93. ;     Receive message descriptor bit definitions.
  94. ;
  95. RCV_OWN        equ    8000h    ; owner bit 0 = host, 1 = lance
  96. RCV_ERR        equ    4000h    ; Error Summary
  97. RCV_FRAM    equ     2000h    ; Framing Error
  98. RCV_OFLO    equ    1000h    ; Overflow Error
  99. RCV_CRC        equ    0800h    ; CRC Error
  100. RCV_BUF_ERR    equ     0400h    ; Buffer Error
  101. RCV_START    equ    0200h    ; Start of Packet
  102. RCV_END        equ    0100h    ; End of Packet
  103.  
  104.  
  105. ;
  106. ;    Transmit  message descriptor bit definitions.
  107. ;
  108. XMIT_OWN    equ    8000h    ; owner bit 0 = host, 1 = lance
  109. XMIT_ERR    equ    4000h   ; Error Summary
  110. XMIT_RETRY    equ    1000h   ; more the 1 retry needed to Xmit
  111. XMIT_1_RETRY    equ    0800h    ; one retry needed to Xmit
  112. XMIT_DEF    equ    0400h    ; Deferred
  113. XMIT_START    equ    0200h    ; Start of Packet
  114. XMIT_END    equ    0100h    ; End of Packet
  115.  
  116. ;
  117. ;    Miscellaneous Equates
  118. ;
  119.  
  120. TRANSMIT_BUF_COUNT    equ    1
  121. RECEIVE_BUF_COUNT    equ    8
  122. TRANSMIT_BUF_SIZE    equ    1518
  123. RECEIVE_BUF_SIZE    equ    1518
  124.  
  125. ;
  126. ;    Receive Message Descriptor
  127. ;
  128. rcv_msg_dscp struc
  129.     rmd0    dw    ?    ; Rec. Buffer Lo-Address
  130.     rmd1    dw    ?    ; Status bits / Hi-Address
  131.     rmd2    dw    ?    ; Buff Byte-length (2's Comp)
  132.     rmd3    dw    ?    ; Receive message length
  133. rcv_msg_dscp ends
  134.  
  135.  
  136. ;
  137. ;    Transmit Message Descriptor
  138. ;
  139. xmit_msg_dscp struc
  140.     tmd0    dw    ?    ; Xmit Buffer Lo-Address
  141.     tmd1    dw    ?    ; Status bits / Hi-Address
  142.     tmd2     dw    ?    ; Buff Byte-length (2's Comp)
  143.     tmd3    dw    ?    ; Buffer Status bits & TDR value
  144. xmit_msg_dscp ends
  145.  
  146. code    segment    para public
  147.     assume    cs:code, ds:code
  148.  
  149.     public    int_no
  150. int_no    db    3,0,0,0            ;must be four bytes long for get_number.
  151. io_addr    dw    300h,0
  152. dma_no    db    5,0,0,0
  153.  
  154.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  155. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  156. driver_type    db    51        ;unused in the packet spec
  157. driver_name    db    'NE2100',0    ;name of the driver.
  158. driver_function    db    2        ;basic, extended
  159. parameter_list    label    byte
  160.     db    1    ;major rev of packet driver
  161.     db    9    ;minor rev of packet driver
  162.     db    14    ;length of parameter list
  163.     db    EADDR_LEN    ;length of MAC-layer address
  164.     dw    GIANT    ;MTU, including MAC headers
  165.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  166.     dw    RECEIVE_BUF_COUNT-1    ;(# of back-to-back MTU rcvs) - 1
  167.     dw    TRANSMIT_BUF_COUNT-1    ;(# of successive xmits) - 1
  168. int_num    dw    0    ;Interrupt # to hook for post-EOI
  169.             ;processing, 0 == none,
  170.  
  171.     public    rcv_modes
  172. rcv_modes    dw    7        ;number of receive modes in our table.
  173.         dw    0               ;There is no mode zero
  174.         dw    rcv_mode_1
  175.         dw    0        ;only ours.
  176.         dw    rcv_mode_3    ;ours plus broadcast
  177.         dw    0        ;some multicasts
  178.         dw    rcv_mode_5    ;all multicasts
  179.         dw    rcv_mode_6    ;all packets
  180.  
  181. ;
  182. ;the LANCE requires that the descriptor pointers be on a qword boundary.
  183. ;
  184.     align    8
  185.  
  186. transmit_dscps    xmit_msg_dscp    TRANSMIT_BUF_COUNT dup(<>)
  187. receive_dscps    rcv_msg_dscp    RECEIVE_BUF_COUNT dup(<>)
  188.  
  189. transmit_head    dw    transmit_dscps    ;->next packet to be filled by host.
  190. receive_head    dw    receive_dscps    ;->next packet to be filled by LANCE.
  191.  
  192. ;
  193. ;      LANCE Initialization Block
  194. ;
  195.     align    2
  196. init_block        label    byte
  197. init_mode        dw    0
  198. init_addr        db    EADDR_LEN dup(?)    ; Our Ethernet address
  199. init_filter        db    8 dup(0)    ;Multicast filter.
  200. init_receive        dw    ?,?        ;Receive Ring Pointer.
  201. init_transmit          dw    ?,?          ;Transmit Ring Pointer.
  202.  
  203.     public    as_send_pkt
  204. ; The Asynchronous Transmit Packet routine.
  205. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  206. ;   interrupts possibly enabled.
  207. ; Exit with nc if ok, or else cy if error, dh set to error number.
  208. ;   es:di and interrupt enable flag preserved on exit.
  209. as_send_pkt:
  210.     ret
  211.  
  212.     public    drop_pkt
  213. ; Drop a packet from the queue.
  214. ; Enter with es:di -> iocb.
  215. drop_pkt:
  216.     assume    ds:nothing
  217.     ret
  218.  
  219.     public    xmit
  220. ; Process a transmit interrupt with the least possible latency to achieve
  221. ;   back-to-back packet transmissions.
  222. ; May only use ax and dx.
  223. xmit:
  224.     assume    ds:nothing
  225.     ret
  226.  
  227.  
  228.     public    send_pkt
  229. send_pkt:
  230. ;enter with ds:si -> packet, cx = packet length.
  231. ;exit with nc if ok, or else cy if error, dh set to error number.
  232.     assume    ds:nothing
  233.  
  234.     cmp    cx,TRANSMIT_BUF_SIZE
  235.     ja    send_err
  236.     xor    bx,bx
  237.  
  238.     mov    ax,18
  239.     call    set_timeout
  240. send_pkt_1:
  241.     test    transmit_dscps[bx].tmd1,XMIT_OWN    ;Did the lance chip give it back?
  242.     je    send_pkt_2
  243.     call    do_timeout
  244.     jne    send_pkt_1
  245. send_err:
  246.     mov    dh,CANT_SEND
  247.     stc
  248.     ret
  249. send_pkt_2:
  250. ;reset error indications.
  251.     and    transmit_dscps[bx].tmd1,not (XMIT_ERR or XMIT_DEF or XMIT_1_RETRY or XMIT_RETRY)    ;Did the lance chip give it back?
  252.     mov    transmit_dscps[bx].tmd3,0    ;reset all error bits.
  253.  
  254.     mov    ax,cx            ;store the count.
  255.     cmp    ax,RUNT            ; minimum length for Ether
  256.     ja    oklen
  257.     mov    ax,RUNT            ; make sure size at least RUNT
  258. oklen:
  259.     neg    ax
  260.     mov    transmit_dscps[bx].tmd2,ax
  261.  
  262.     mov    ax,transmit_dscps[bx].tmd0    ;store the packet.
  263.     mov    dx,transmit_dscps[bx].tmd1
  264.     call    phys_to_segmoffs
  265.     rep    movsb
  266.  
  267.     or    transmit_dscps[bx].tmd1,XMIT_OWN or XMIT_START or XMIT_END    ;give it to the lance chip.
  268.  
  269. ;Inform LANCE that it should poll for a packet.
  270.     mov    ax,CSR0_INEA or CSR0_TDMD
  271.     outport    CSR0
  272.     clc
  273.     ret
  274.  
  275.  
  276.     public    get_address
  277. get_address:
  278. ;get the address of the interface.
  279. ;enter with es:di -> place to get the address, cx = size of address buffer.
  280. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  281.     assume    ds:code
  282.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  283.     jb    get_address_2
  284.     mov    cx,EADDR_LEN
  285.     mov    dx,io_addr        ; Get our Ethernet address base.
  286.     add    dx,NODE_REG
  287.     cld
  288. get_address_1:
  289.     insb                ; get a byte of the rom address
  290.     inc    dx            ; next register
  291.     loop    get_address_1        ; go back for rest
  292.     mov    cx,EADDR_LEN
  293.     clc
  294.     ret
  295. get_address_2:
  296.     stc
  297.     ret
  298.  
  299.  
  300.     public    set_address
  301. set_address:
  302. ;enter with ds:si -> Ethernet address, CX = length of address.
  303. ;exit with nc if okay, or cy, dh=error if any errors.
  304.     assume    ds:nothing
  305.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  306.     je    set_address_4
  307.     mov    dh,BAD_ADDRESS
  308.     stc
  309.     jmp    short set_address_done
  310. set_address_4:
  311.  
  312.     push    cs
  313.     pop    es
  314.     mov    di,offset init_addr
  315.     rep    movsb
  316.     call    initialize        ;initialize with our new address.
  317.  
  318. set_address_okay:
  319.     mov    cx,EADDR_LEN        ;return their address length.
  320.     clc
  321. set_address_done:
  322.     push    cs
  323.     pop    ds
  324.     assume    ds:code
  325.     ret
  326.  
  327.  
  328. rcv_mode_1:
  329.     mov    ax,M_DRX or M_DTX    ;disable the receiver and transmitter.
  330.     jmp    initialize_nomulti
  331. rcv_mode_3:
  332.     xor    ax,ax            ;don't accept any multicast frames.
  333.     call    initialize_multi
  334.     mov    ax,0            ;non-promiscuous mode
  335.     jmp    short initialize_nomulti
  336. rcv_mode_5:
  337.     mov    ax,-1            ;accept any multicast frames.
  338.     call    initialize_multi
  339.     mov    ax,0            ;non-promiscuous mode
  340.     jmp    short initialize_nomulti
  341. rcv_mode_6:
  342.     mov    ax,M_PROM    ;promiscuous mode
  343. initialize_nomulti:
  344. initialize:
  345.     mov    init_mode,ax
  346.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  347.     outport    CSR0
  348.  
  349.     mov    ax,CSR0_INEA or CSR0_STRT or CSR0_INIT    ;reinit and restart.
  350.     outport    CSR0
  351.  
  352.     mov    ax,36            ;wait one second for the board
  353.     call    set_timeout        ;  to timeout.
  354. initialize_1:
  355.     in    ax,dx
  356.     test    ax,CSR0_IDON
  357.     jne    initialize_2
  358.     call    do_timeout
  359.     jne    initialize_1
  360.     stc
  361.     ret
  362. initialize_2:
  363.     clc
  364.     ret
  365.  
  366.  
  367. initialize_multi:
  368. ;enter with ax = value for all multicast hash bits.
  369.     push    cs
  370.     pop    es
  371.     mov    di,offset init_filter
  372.     mov    cx,8/2
  373.     rep    stosw
  374.     ret
  375.  
  376.  
  377.     public    set_multicast_list
  378. set_multicast_list:
  379. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  380. ;return nc if we set all of them, or cy,dh=error if we didn't.
  381.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  382.     stc
  383.     ret
  384.  
  385.  
  386.     public    terminate
  387. terminate:
  388.     call    rcv_mode_1        ;don't receive any apckets.
  389.  
  390. ;This routine will remove the (host) DMA controller from
  391. ;cascade mode of operation.
  392.     mov    al,dma_no
  393.     or    al,SET_DMA_MASK
  394.     cmp    dma_no,4        ;If channel 5 or 6,
  395.     ja    terminate_16        ;  use sixteen bit dma.
  396. terminate_8:
  397.     out    DMA_8MASK_REG,al
  398.     jmp    short terminate_done
  399. terminate_16:
  400.     out    DMA_16MASK_REG,al
  401. terminate_done:
  402.     ret
  403.  
  404.     public    reset_interface
  405. reset_interface:
  406. ;reset the interface.
  407.     assume    ds:code
  408.     ret
  409.  
  410.  
  411. ;called when we want to determine what to do with a received packet.
  412. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  413.     extrn    recv_find: near
  414.  
  415. ;called after we have copied the packet into the buffer.
  416. ;enter with ds:si ->the packet, cx = length of the packet.
  417.     extrn    recv_copy: near
  418.  
  419.     extrn    count_in_err: near
  420.     extrn    count_out_err: near
  421.  
  422. LANCE_ISR_ACKNOWLEDGE equ (CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  423.  
  424.     public    recv
  425. recv:
  426. ;called from the recv isr.  All registers have been saved, and ds=cs.
  427. ;Upon exit, the interrupt will be acknowledged.
  428.     assume    ds:code
  429.  
  430.     mov    dx,io_addr
  431.     add    dx,ADDR_REG
  432.     mov    ax,CSR0
  433.     out    dx,ax
  434.     in    ax,dx
  435.     dec    dx
  436.     dec    dx
  437.     in    ax,dx
  438.     mov    bx,ax            ;make a copy.
  439.  
  440. ; Acknowledge the Interrupt from the controller, but disable further
  441. ; controller Interrupts until we service the current interrupt.
  442. ;
  443. ;(CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  444. ;
  445.     and    ax,not LANCE_ISR_ACKNOWLEDGE
  446.     out    dx,ax
  447.     in    ax,dx        ; follow all writes by a read
  448.  
  449.     test    bx,CSR0_RINT        ;receive interrupt?
  450.     je    recv_done        ;no, we're done.
  451.  
  452.     mov    bx,receive_head
  453.  
  454. recv_search:
  455.     test    code:[bx].rmd1,RCV_OWN    ;do we own this buffer?
  456.     je    recv_own        ;yes - process it.
  457.     call    inc_recv_ring        ;go to the next one.
  458.     cmp    bx,receive_head        ;did we get back to the beginning?
  459.     jne    recv_search        ;not yet.
  460.     jmp    short recv_done        ;yes -- spurious interrupt!
  461. recv_own:
  462.     test    code:[bx].rmd1,RCV_ERR    ;Any errors in this buffer?
  463.     jne    recv_err        ;yes -- ignore this packet.
  464.  
  465.     mov    ax,code:[bx].rmd0    ;fetch the packet.
  466.     mov    dx,code:[bx].rmd1
  467.     call    phys_to_segmoffs
  468.  
  469.     push    es
  470.     push    di
  471.     push    bx
  472.  
  473.     mov    cx,code:[bx].rmd3
  474.     and    cx,0fffh        ;strip off the reserved bits
  475.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  476.                     ;  point to the packet type.
  477.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  478.     mov    ax, es:[di]
  479.     xchg    ah, al
  480.     cmp     ax, 1500
  481.     ja    BlueBookPacket
  482.     inc    di            ;set di to 802.2 header
  483.     inc    di
  484.     mov    dl, IEEE8023
  485. BlueBookPacket:
  486.     push    cx
  487.     call    recv_find
  488.     pop    cx
  489.  
  490.     pop    bx
  491.     pop    si
  492.     pop    ds
  493.     assume    ds:nothing
  494.  
  495.     mov    ax,es            ;is this pointer null?
  496.     or    ax,di
  497.     je    recv_free        ;yes - just free the frame.
  498.  
  499.     push    es
  500.     push    di
  501.     push    cx
  502.     rep    movsb
  503.     pop    cx
  504.     pop    si
  505.     pop    ds
  506.     assume    ds:nothing
  507.  
  508.     call    recv_copy
  509.  
  510.     jmp    short recv_free
  511.  
  512. recv_err:
  513.     call    count_in_err
  514. recv_free:
  515.     push    cs
  516.     pop    ds
  517.     assume    ds:code
  518.  
  519. ;clear any error bits.
  520.     and    code:[bx].rmd1,not (RCV_ERR or RCV_FRAM or RCV_OFLO or RCV_CRC or RCV_BUF_ERR)
  521.     or    code:[bx].rmd1,RCV_OWN    ;give it back to the lance.
  522.     call    inc_recv_ring        ;go to the next one.
  523.     test    code:[bx].rmd1,RCV_OWN    ;Do we own this one?
  524.     je    recv_own
  525.     mov    receive_head,bx        ;remember where the next one starts.
  526. recv_done:
  527.     mov    dx,io_addr        ;enable interrupts again.
  528.     add    dx,DATA_REG
  529.     mov    ax,CSR0_INEA
  530.     out    dx,ax
  531.     ret
  532.  
  533.  
  534. inc_recv_ring:
  535. ;advance bx to the next receive ring descriptor.
  536.     assume    ds:nothing
  537.     add    bx,(size rcv_msg_dscp)
  538.     cmp    bx,offset receive_dscps + RECEIVE_BUF_COUNT * (size rcv_msg_dscp)
  539.     jb    inc_recv_ring_1
  540.     mov    bx,offset receive_dscps
  541. inc_recv_ring_1:
  542.     ret
  543.  
  544.  
  545.     public    recv_exiting
  546. recv_exiting:
  547. ;called from the recv isr after interrupts have been acknowledged.
  548. ;Only ds and ax have been saved.
  549.     assume    ds:nothing
  550.     ret
  551.  
  552.  
  553. phys_to_segmoffs:
  554. ;enter with dx:ax as the physical address of the buffer,
  555. ;exit with es:di -> buffer.
  556.     shl    dx,16-4            ;move the upper four bits into position.
  557.     mov    di,ax            ;now get the low 12 bits of the segment.
  558.     shr    di,4
  559.     or    dx,di            ;combine them.
  560.     mov    es,dx
  561.     mov    di,ax
  562.     and    di,0fh            ;now compute the offset.
  563.     ret
  564.  
  565.     include    timeout.asm
  566.  
  567. ;we use this memory for buffers once we've gone resident.
  568.     align    2
  569. transmit_bufs    equ    $
  570. receive_bufs    equ    transmit_bufs + TRANSMIT_BUF_COUNT * TRANSMIT_BUF_SIZE
  571. end_resident    equ    receive_bufs + RECEIVE_BUF_COUNT * RECEIVE_BUF_SIZE
  572.  
  573.     public    usage_msg
  574. usage_msg    db    "usage: ne2100 [-n] [-d] [-w] <packet_int_no> [int_no] [io_addr] [dma_no]",CR,LF,'$'
  575. bad_reset_msg    db    "Unable to reset the NE2100.",CR,LF,'$'
  576. bad_init_msg    db    "Unable to initialize the NE2100.",CR,LF,'$'
  577.  
  578.     public    copyright_msg
  579. copyright_msg    db    "Packet driver for an NE2100, version ",'0'+majver/10,'0'+(majver mod 10),".",'0'+version,CR,LF
  580.         db    '$'
  581.  
  582. int_no_name    db    "Interrupt number ",'$'
  583. io_addr_name    db    "I/O port ",'$'
  584. dma_no_name    db    "DMA number ",'$'
  585.  
  586.     extrn    set_recv_isr: near
  587.     extrn    maskint: near
  588.  
  589. ;enter with si -> argument string, di -> dword to store.
  590. ;if there is no number, don't change the number.
  591.     extrn    get_number: near
  592.  
  593. ;enter with dx -> name of word, di -> dword to print.
  594.     extrn    print_number: near
  595.  
  596.     public    parse_args
  597. parse_args:
  598. ;exit with nc if all went well, cy otherwise.
  599.     assume    ds:code
  600.     mov    di,offset int_no
  601.     call    get_number
  602.     mov    di,offset io_addr
  603.     call    get_number
  604.     mov    di,offset dma_no
  605.     call    get_number
  606.     clc
  607.     ret
  608.  
  609.  
  610.     public    etopen
  611. etopen:
  612.     assume    ds:code
  613.  
  614. ;This routine will put the (host) DMA controller into
  615. ;cascade mode of operation.
  616.  
  617.     mov    al,dma_no
  618.     cmp    al,4            ;If channel 5, 6 or 7
  619.     ja    dma_16            ;  use sixteen bit dma.
  620. dma_8:
  621.     or    al,CASCADE_MODE
  622.     out    DMA_8MODE_REG,al
  623.     and    al,DMA_CHANNEL_FIELD
  624.     out    DMA_8MASK_REG,al
  625.     jmp    short dma_done
  626. dma_16:
  627.     and    al,DMA_CHANNEL_FIELD
  628.     out    DMA_16MASK_REG,al
  629.     or    al,CASCADE_MODE
  630.     out    DMA_16MODE_REG,al
  631. dma_done:
  632.  
  633.     mov    al, int_no        ; Get board's interrupt vector
  634.     add    al, 8
  635.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  636.     jb    set_int_num        ; No.
  637.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  638. set_int_num:
  639.     xor    ah, ah            ; Clear high byte
  640.     mov    int_num, ax        ; Set parameter_list int num.
  641.  
  642.     mov    al,int_no
  643.     call    maskint            ;disable these interrupts.
  644.  
  645.     mov    ax,0ff7ch        ;stop LANCE
  646.     outport CSR0            ;should use hardware reset here
  647.  
  648.     mov    ax,20
  649.     call    set_timeout
  650. etreset:
  651.     mov    dx,io_addr
  652.     add    dx,DATA_REG
  653.     xor    ax,ax
  654.     in    ax,dx
  655.     test    ax,CSR0_STOP
  656.     jnz    reset_ok
  657.     call    do_timeout
  658.     jnz    etreset
  659.  
  660.     mov    dx,offset bad_reset_msg
  661.     mov    ah,9
  662.     int    21h
  663.  
  664.     stc
  665.     ret
  666. reset_ok:
  667.  
  668. ;set up transmit descriptor ring.
  669.     push    ds
  670.     pop    es
  671.     mov    cx,TRANSMIT_BUF_COUNT
  672.     mov    bx,offset transmit_dscps
  673.     mov    di,offset transmit_bufs
  674. setup_transmit:
  675.     call    segmoffs_to_phys
  676.  
  677.     or    dx,XMIT_START or XMIT_END
  678.     mov    [bx].tmd0,ax        ;points to the buffer.
  679.     mov    [bx].tmd1,dx
  680.  
  681.     add    bx,(size xmit_msg_dscp)
  682.     add    di,TRANSMIT_BUF_SIZE
  683.     loop    setup_transmit
  684.  
  685. ;set up receive descriptor ring.
  686.     mov    cx,RECEIVE_BUF_COUNT
  687.     mov    bx,offset receive_dscps
  688.     mov    di,offset receive_bufs
  689. setup_receive:
  690.     call    segmoffs_to_phys
  691.  
  692.     or    dx,RCV_OWN
  693.     mov    [bx].rmd0,ax        ;points to the buffer.
  694.     mov    [bx].rmd1,dx
  695.  
  696.     mov    [bx].rmd2,-RECEIVE_BUF_SIZE
  697.     mov    [bx].rmd3,0
  698.  
  699.   if 0
  700.     push    di            ;initialize the buffers to 55aa.
  701.     push    cx
  702.     mov    cx,RECEIVE_BUF_SIZE/2
  703.     mov    ax,55aah
  704.     rep    stosw
  705.     pop    cx
  706.     pop    di
  707.   endif
  708.  
  709.     add    bx,(size rcv_msg_dscp)
  710.     add    di,RECEIVE_BUF_SIZE
  711.     loop    setup_receive
  712.  
  713. ;initialize the board.
  714.     mov    cx,EADDR_LEN        ;get our address.
  715.     mov    di,offset init_addr
  716.     call    get_address
  717.  
  718.     mov    cx,RECEIVE_BUF_COUNT
  719.     call    compute_log2
  720.  
  721.     mov    di,offset receive_dscps
  722.     call    segmoffs_to_phys
  723.     or    dx,cx            ;include the buffer size bits.
  724.     mov    init_receive[0],ax
  725.     mov    init_receive[2],dx
  726.  
  727.     mov    cx,TRANSMIT_BUF_COUNT
  728.     call    compute_log2
  729.  
  730.     mov    di,offset transmit_dscps
  731.     call    segmoffs_to_phys
  732.     or    dx,cx            ;include the buffer size bits.
  733.     mov    init_transmit[0],ax
  734.     mov    init_transmit[2],dx
  735.  
  736.     mov    di,offset init_block    ;now tell the board where the init
  737.     call    segmoffs_to_phys    ;  block is.
  738.  
  739.     push    dx
  740.     push    ax
  741.  
  742.     mov    ax,0            ;write the bus config register.
  743.     outport    CSR3
  744.  
  745.     pop    ax            ;write the low word.
  746.     outport    CSR1
  747.  
  748.     pop    ax            ;write the high word.
  749.     outport    CSR2
  750.  
  751.     mov    ax,0            ;non-promiscuous mode
  752.     call    initialize
  753.     jnc    init_ok
  754.  
  755.     mov    dx,offset bad_init_msg
  756.     mov    ah,9
  757.     int    21h
  758.  
  759.     stc
  760.     ret
  761.  
  762. init_ok:
  763. ;
  764. ; Now hook in our interrupt
  765. ;
  766.     call    set_recv_isr
  767.  
  768.     mov    dx,offset end_resident
  769.     clc
  770.     ret
  771.  
  772.     public    print_parameters
  773. print_parameters:
  774. ;echo our command-line parameters
  775.     mov    di,offset int_no
  776.     mov    dx,offset int_no_name
  777.     call    print_number
  778.     mov    di,offset io_addr
  779.     mov    dx,offset io_addr_name
  780.     call    print_number
  781.     mov    di,offset dma_no
  782.     mov    dx,offset dma_no_name
  783.     call    print_number
  784.     ret
  785.  
  786. compute_log2:
  787. ;enter with cx = number of buffers.
  788. ;exit with cx = log2(number of buffers) << 13.
  789.     mov    ax,-1
  790. compute_log2_1:
  791.     inc    ax
  792.     shr    cx,1
  793.     jne    compute_log2_1
  794.     shl    ax,13
  795.     mov    cx,ax
  796.     ret
  797.  
  798.  
  799. segmoffs_to_phys:
  800. ;enter with es:di -> buffer.
  801. ;exit with dx:ax as the physical address of the buffer,
  802.  
  803.     mov    dx,es            ;get the high 4 bits of the segment,
  804.     shr    dx,16-4
  805.     mov    ax,es            ;and the low 12 bits of the segment.
  806.     shl    ax,4
  807.     add    ax,di            ;add in the offset.
  808.     adc    dx,0
  809.     ret
  810.  
  811.  
  812. code    ends
  813.  
  814.     end
  815.  
  816.